package com.wolfeyes.framework.shiro.realms;

//import com.wolfeyes.common.utils.ApplicationContextUtils;
import com.wolfeyes.common.utils.JwtUtil;
import com.wolfeyes.framework.shiro.JwtToken;
import com.wolfeyes.system.domain.SysUser;
//import com.wolfeyes.system.service.SysUserService;
import com.wolfeyes.system.service.impl.SysUserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
//import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @description 实现Shiro框架授权领域接口AuthorizingRealm的业务逻辑
 * @see Talk is cheap, Show me the code. -- Linus Torvalds
 * @title 自定义realm
 * @title Realm 是 shiro 的核心组件，主要处理两大功能：
 * @title 1.认证 我们接收 filter 传过来的 token，并认证 login 操作的 token
 * @title 2.授权 获取到登录用户信息，并取得用户的权限存入 roles，以便后期对接口进行操作权限验证.
 * @author yanyljava
 * @create 2022-01-04 21:25
 */
@Slf4j
public class CustomizeRealm extends AuthorizingRealm {

	@Autowired
	private SysUserServiceImpl sysUserService;

	/**
	 * @description 重写此方法避免shiro报错
	 * @param token shiro框架下的身份验证的抽象接口，该接口会返回2个信息，用户信息（Principal）和凭证信息（Credentials）
	 * @return 是否支持验证的判定结果
	 */
	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof JwtToken;
	}

	/**
	 * @description 获取用户授权信息（权限集合）
	 * @param principalCollection shiro框架下的用户信息的抽象接口
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		// 这里是返回用户的权限集合
		return null;
	}

	/**
	 * @description 获取用户身份认证信息
	 * @param authenticationToken shiro框架下的身份验证的抽象接口，该接口会返回2个信息，用户信息（Principal）和凭证信息（Credentials）
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		String token = (String) authenticationToken.getCredentials();
		// 解密获得username，用于和数据库进行对比
		String username = null;
		try {
			//这里工具类没有处理空指针等异常这里处理一下(这里处理科学一些)
			username = JwtUtil.getUsername(token);
		} catch (Exception e) {
			throw new AuthenticationException("token拼写错误或者值为空");
		}
		if (username == null) {
			log.error("token无效(空''或者null都不行!)");
			throw new AuthenticationException("token无效");
		}
		SysUser user = sysUserService.findByName(username);
		if (user == null) {
			log.error("用户不存在)");
			throw new AuthenticationException("用户不存在");
		}
		// 校验Token的有效性
		if (!JwtUtil.verify(token, username, user.getPassword())) {
			log.error("用户名或密码错误(token无效或者与登录者不匹配)");
			throw new AuthenticationException("用户名或密码错误(token无效或者与登录者不匹配)");
		}
		// 根据token获取用户信息，创建身份认证信息对象SimpleAuthenticationInfo返回给shiro框架
		return new SimpleAuthenticationInfo(token, token, this.getName());
	}
}
